import { Vector2 } from 'three';

interface Delta {
  pan?: Vector2
}

interface InertiaItem {
  time: number;
  delta: Delta;
}

const PAN_LINEARITY = 0.3;
const PAN_MAX_SPEED = 1400;
const PAN_DECELERATION = 2500;

const ROTATE_LINEARITY = 0.25;
const ROTATE_MAX_SPEED = 180;
const ROTATE_DECELERATION = 720;

const ZOOM_LINEARITY = 0.15;
const ZOOM_MAX_SPEED = 2.5;
const ZOOM_DECELERATION = 12;

const panInertiaOption = {
  linearity: 0.3,
  maxSpeed: 1400,
  deceleration: 2500,
};

// const rotateInertia = {
//   linearity: 0.25,
//   maxSpeed: 180,
//   deceleration: 720,
// };

class Inertia {
  private _inertias: InertiaItem[] = [];

  record(delta: Delta) {
    this._inertias.push({ time: performance.now(), delta });
    this._drainInertias();
  }

  private _drainInertias() {
    const now = performance.now();

    let index = -1;
    for (let i = this._inertias.length - 1; i >= 0; i -= 1) {
      if (now - this._inertias[i].time > 160) {
        index = i;
        break;
      }
    }
    if (index !== -1) {
      this._inertias = this._inertias.slice(index + 1);
    }
  }

  calculate() {
    this._drainInertias();
    if (this._inertias.length < 2) return;
    const start = this._inertias[0];
    const end = this._inertias[this._inertias.length - 1];
    this._panInertia(start, end);
  }

  // eslint-disable-next-line class-methods-use-this
  private _panInertia(start: InertiaItem, end: InertiaItem) {
    const startPan = start.delta.pan;
    const endPan = end.delta.pan;
    if (!startPan || !endPan) return;
    const offset = endPan.clone().sub(startPan);
    const duration = (end.time - start.time) / 1000;
    if (offset.length() === 0 || duration === 0) return;
    const velocity = offset.multiplyScalar(panInertiaOption.linearity / duration);
    const length = velocity.length();
    let speed = length;
    if (speed > panInertiaOption.maxSpeed) {
      speed = panInertiaOption.maxSpeed;
      velocity.multiplyScalar(speed / length);
    }
    const animateDuration = speed / (panInertiaOption.deceleration * panInertiaOption.linearity) * 1000;
    const endCenter = velocity.multiplyScalar(duration / 2);
  }
}

export default Inertia;
